package com.symone.crawler.service;

import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.symone.crawler.App;
import com.symone.crawler.action.Catcher;
import com.symone.crawler.config.AirBnbConfig;
import com.symone.crawler.config.CrawlerConfig;
import com.symone.crawler.data.ProxyData;
import com.symone.crawler.log.Log;
import com.symone.crawler.log.LogFactory;

import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class SearchService {

    private static Log logger = LogFactory.getLog(SearchService.class);
    private volatile Catcher catcher = new Catcher();

    private int page;
    private int minPrice;
    private int maxPrice;
    private ProxyData proxy;
    private Map<String,String> params;

    public SearchService(int page ,int curPrice ,int addPrice){
        this.page = page;
        this.minPrice = curPrice;
        this.maxPrice = curPrice + addPrice;

        params = new HashMap<>();
        params.put("items_offset", String.valueOf(AirBnbConfig.page_num * (page-1)));
        params.put("items_per_grid", String.valueOf(AirBnbConfig.page_num));
        params.put("price_min", String.valueOf(minPrice));
        params.put("price_max", String.valueOf(maxPrice));
        params.put("query", AirBnbConfig.city);
        params.put("key", AirBnbConfig.key);
        params.put("_format", "for_explore_search_web");
        params.put("selected_tab_id", "home_tab");
        params.put("currency", "CNY");
    }

    public void saveWithFetch(boolean useProxy) {
        synchronized (this) {
            try {
                String result = null;
                if(useProxy){
                    int reIndex = 0;
                    while (true) {
                        if(reIndex >= CrawlerConfig.MAX_RETRY){
                            logger.error("URL 重试多次访问失败! URL:" + AirBnbConfig.LIST_URL + " PARAMS:" + JSONUtil.toJsonStr(params));
                            return;
                        }
                        proxy = App.PROXY_THREAD_MAP.get(Thread.currentThread().getId());
                        if(proxy == null || proxy.getExpireTime().before(new Date())){
                            proxy = ProxyService.getProxyData();
                            logger.info("PROXY [" + proxy.getIp() + ":"  + proxy.getPort() + "    -   "  + CrawlerConfig.DATETIME_FORMATTER.format(proxy.getExpireTime()) + "] is Using ......");
                        }
                        try {
                            result = catcher.catchDocumentWithProxy(AirBnbConfig.LIST_URL, this.params, proxy).body();
                            //logger.info("-------------------  RETRY " + retry + " - " +reIndex);
                        } catch (Exception ex) {
                            //ex.printStackTrace();
                            logger.error("--->  RETRY [ " + reIndex + " ] 获取数据失败!" + ex.getMessage());
                            Thread.sleep((long) 1000);
                        }
                        if( result != null){
                            break;
                        }
                        reIndex ++;
                    }
                }else{
                    result = catcher.catchDocument(AirBnbConfig.LIST_URL, params).body();
                }
                saveData(result);
            } catch (Exception e) {
                e.printStackTrace();
                //logger.error("获取数据失败!" + e.getMessage());
            } finally {
                //logger.info("总次数/成功次数/失败次数："+ total +"/"+success + "/"+failed);
            }
        }
    }

    private void saveData(String json){
        JSONArray sections = JSONUtil.parseObj(json).getJSONArray("explore_tabs").getJSONObject(0).getJSONArray("sections");
        for(int i = 0 ; i < sections.size() ; i ++){
            if(sections.getJSONObject(i).getStr("result_type").equals("listings")){
                JSONArray listings = sections.getJSONObject(i).getJSONArray("listings");
                for(int j = 0 ; j < listings.size() ; j ++){
                    Long roomId = listings.getJSONObject(j).getJSONObject("listing").getLong("id");
                    Long userId = listings.getJSONObject(j).getJSONObject("listing").getJSONObject("user").getLong("id");
                    logger.info("Get RoomID : " + roomId);

                    try {
                        Entity roomEntity = Entity.create("airbnb_room");
                        roomEntity.set("id",roomId);
                        if(Db.use().count(roomEntity) == 0 ) {
                            roomEntity.set("user_id",userId);
                            Db.use().insert(roomEntity);
                        }
                        Entity userEntity = Entity.create("airbnb_user");
                        userEntity.set("id",userId);
                        if(Db.use().count(userEntity) == 0 ) {
                            Db.use().insert(userEntity);
                        }
                    } catch (SQLException e) {
                        logger.info("Save RoomID [ " + roomId + " ] ERROR,Exception:" + e.getMessage());
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
